package org.msb.accentis.data.pojo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;

import org.msb.accentis.data.CategoryType;

@Entity
@NamedQueries({
		@NamedQuery(name = "Category.getCategoriesByType", query = "SELECT c FROM Category c WHERE c.categoryType = :type AND c.parentCategory IS NULL"),
		@NamedQuery(name = "Category.getAllCategories", query = "SELECT c FROM Category c WHERE c.parentCategory IS NULL ORDER BY c.categoryType, c.name") })
public class Category extends NamedObject {

	private static final String SEPARATOR = ":"; //$NON-NLS-1$
	
	@ManyToOne(cascade = CascadeType.ALL)
	private Category parentCategory;

	@Basic
	private CategoryType categoryType = CategoryType.INCOME;

	@OneToMany(cascade = CascadeType.ALL)
	@OrderBy
	private List<Category> subCategories = new ArrayList<Category>();
	
	@Override
	public String getName() {
		int pos = super.getName().indexOf(':');
		if (-1 == pos)
			return super.getName();

		return super.getName().substring(pos + 1);
	}

	@Override
	public void setName(String value) {
		if (null == parentCategory)
			super.setName(value);
		else
			super.setName(parentCategory.getName() + SEPARATOR + value);
	}

	public Category getParentCategory() {
		return parentCategory;
	}

	public void setParentCategory(Category value) {
		String categoryName = getName();
		
		parentCategory = value;

		if (null != value) {
			categoryType = value.getCategoryType();
			int pos = Collections.binarySearch(value.subCategories, this);
			if (0 > pos)
				value.subCategories.add(-pos - 1, this);
		}
		
		setName(categoryName);
	}

	public List<Category> getSubCategories() {
		return subCategories;
	}
	
	public CategoryType getCategoryType() {
		return categoryType;
	}

	public boolean isIncome() {
		return categoryType.equals(CategoryType.INCOME);
	}

	public boolean isExpense() {
		return categoryType.equals(CategoryType.EXPENSE);
	}

	public void setCategoryType(CategoryType value) {
		categoryType = value;
		
		for (Category subCategory : subCategories)
			subCategory.categoryType = value;
	}

	public boolean isSubCategory() {
		return null != parentCategory;
	}
}
